package com.btb.adapter.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.btb.adapter.constant.Constants;
import com.btb.adapter.constant.QueryType;
import com.btb.adapter.exception.QueryUpChainResultException;
import com.btb.adapter.mapper.UpChainFishMapper;
import com.btb.adapter.mapper.UpChainFishPartMapper;
import com.btb.adapter.mapper.UpChainHeroMapper;
import com.btb.adapter.model.UpChainFish;
import com.btb.adapter.model.UpChainFishExample;
import com.btb.adapter.model.UpChainFishPart;
import com.btb.adapter.model.UpChainHero;
import com.btb.adapter.model.UpChainHeroExample;
import com.btb.adapter.vo.request.FishUpChain;
import com.btb.adapter.vo.request.HeroUpChain;
import com.btb.adapter.vo.request.QueryPage;
import com.btb.adapter.vo.request.UpChainPageResult;
import com.btb.adapter.vo.request.UpChainQuery;
import com.btb.adapter.vo.request.UpChainResult;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;

/**
 * @author hqbzl
 *
 *         上链操作
 *
 */
@Service
public class UpChainApiService {
	@Autowired
	private UpChainHeroMapper upChainHeroMapper;
	@Autowired
	private UpChainFishMapper upChainFishMapper;
	@Autowired
	private UpChainFishPartMapper upChainFishPartMapper;

	public String heroUpChain(final HeroUpChain heros) {
		final String requestId = UUID.randomUUID().toString();
		List<UpChainHero> upChainHeros = new ArrayList<>();
		heros.getList().forEach(x -> {
			UpChainHero build = x.build(heros.getOwner(), requestId);
			upChainHeros.add(build);
		});
		if (!upChainHeros.isEmpty()) {
			upChainHeroMapper.batchInsert(upChainHeros);
		}
		return requestId;
	}

	@Transactional(rollbackFor = Exception.class)
	public String fishoUpChain(final FishUpChain fishs) {
		final String requestId = UUID.randomUUID().toString();
		final String owner = fishs.getOwner();
		ArrayList<UpChainFish> upChainFishlist = Lists.newArrayList();
		ArrayList<UpChainFishPart> upChainFishPartList = Lists.newArrayList();
		fishs.getList().forEach(x -> {
			upChainFishlist.add(x.buildFish(owner, requestId));
			upChainFishPartList.addAll(x.buildFishPart());
		});
		if (!upChainFishlist.isEmpty() && !upChainFishPartList.isEmpty()) {
			upChainFishMapper.batchInsert(upChainFishlist);
			upChainFishPartMapper.batchInsert(upChainFishPartList);
		}
		return requestId;
	}

	public UpChainResult queryWithRequestId(final String type, final String requestId) {
		boolean check = QueryType.check(type);
		if (!check) {
			throw new QueryUpChainResultException("type param error");
		}
		List<UpChainQuery> list = null;
		String owner = "";
		if (QueryType.type(type) == QueryType.FISH) {
			List<UpChainFish> fishs = queryFish(requestId);
			owner = fishs.stream().findAny().map(UpChainFish::getOwner).orElse("");
			list = UpChainResult.buildWithFish(fishs);
		} else if (QueryType.type(type) == QueryType.HERO) {
			List<UpChainHero> heros = queryHero(requestId);
			owner = heros.stream().findAny().map(UpChainHero::getOwner).orElse("");
			list = UpChainResult.buildWithHero(heros);
		} else {
			throw new QueryUpChainResultException("type param error");
		}
		if (Objects.nonNull(list)) {
			return UpChainResult.builder().requestId(requestId).owner(owner).type(type).list(list).build();
		}
		return null;
	}

	public QueryPage<UpChainPageResult> queryUpChainResultWithAddress(final String type, final String address,
			final Long pageNo) {
		boolean check = QueryType.check(type);
		if (!check) {
			throw new QueryUpChainResultException("type param error");
		}
		List<UpChainQuery> list = null;
		QueryPage<UpChainPageResult> build = QueryPage.<UpChainPageResult>builder().build();
		if (QueryType.type(type) == QueryType.FISH) {
			final Page<UpChainFish> page = queryFishWithAddress(address, pageNo);
			list = UpChainResult.buildWithFish(page.getResult());
			build.setPageSize(page.getPageSize());
			build.setPageNo(pageNo.intValue());
			build.setPageTotal(page.getPages());
			build.setTotal(page.getTotal());
		} else if (QueryType.type(type) == QueryType.HERO) {
			final Page<UpChainHero> page = queryHeroWithAddress(address, pageNo);
			list = UpChainResult.buildWithHero(page.getResult());
			build.setPageSize(page.getPageSize());
			build.setPageNo(pageNo.intValue());
			build.setPageTotal(page.getPages());
			build.setTotal(page.getTotal());
		} else {
			throw new QueryUpChainResultException("type param error");
		}
		if (Objects.nonNull(list)) {
			UpChainPageResult data = UpChainPageResult.builder().address(address).type(type).list(list).build();
			build.setData(data);
			return build;
		}
		return null;
	}

	public List<UpChainFish> queryFish(final String requestId) {
		UpChainFishExample example = new UpChainFishExample();
		example.createCriteria().andRequestIdEqualTo(requestId);
		return upChainFishMapper.selectByExample(example);
	}

	public List<UpChainHero> queryHero(final String requestId) {
		UpChainHeroExample example = new UpChainHeroExample();
		example.createCriteria().andRequestIdEqualTo(requestId);
		return upChainHeroMapper.selectByExample(example);
	}

	public Page<UpChainFish> queryFishWithAddress(final String address, final Long pageNo) {
		Page<UpChainFish> page = PageHelper.startPage(pageNo.intValue(), Constants.PAGE_SIZE).doSelectPage(() -> {
			UpChainFishExample example = new UpChainFishExample();
			example.createCriteria().andOwnerEqualTo(address);
			upChainFishMapper.selectByExample(example);
		});
		return page;
	}

	public Page<UpChainHero> queryHeroWithAddress(final String address, final Long pageNo) {
		Page<UpChainHero> page = PageHelper.startPage(pageNo.intValue(), Constants.PAGE_SIZE).doSelectPage(() -> {
			UpChainHeroExample example = new UpChainHeroExample();
			example.createCriteria().andOwnerEqualTo(address);
			upChainHeroMapper.selectByExample(example);
		});
		return page;
	}

	/**
	 * 英雄上链
	 *
	 * @return
	 */
	public boolean hero() {
		return true;
	}

	/**
	 * 鱼上链
	 *
	 * @return
	 */
	public boolean fish() {

		return true;
	}

}
